using System;
using System.Collections.Generic;
using System.Text;
using DslFactory.Utilities.DteCodeModel;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Modeling;
using System.Net.Security;
using System.ServiceModel;

namespace Dslfactory.wcfLanguage
{
 internal static class ServiceIncrementalCodeGeneration
 {
  /// <summary>
  /// Subscribe to Interface code generation events
  /// </summary>
  /// <param name="Store"></param>
  /// <param name="eventManagerDirectory"></param>
  public static void SubsribeToStoreEvents(Store Store)
  {
   EventManagerDirectory eventManagerDirectory = Store.EventManagerDirectory;

   // When a property of the Interface changes, the [ContractAttribute] must be updated in code
   eventManagerDirectory.ElementPropertyChanged.Add(Store.DomainDataDirectory.GetDomainClass(typeof(Service)),
                                                          new EventHandler<ElementPropertyChangedEventArgs>(EnsureAttribute));
  }


  /// <summary>
  /// Ensure an attribute for interfaces
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="arg"></param>
  private static void EnsureAttribute(object sender, ElementPropertyChangedEventArgs arg)
  {
   Service service = arg.ModelElement as Service;

   // Name
   if (arg.DomainProperty.Id == Service.NameDomainPropertyId)
   {
    // Get the class
    string oldFullName = (string.IsNullOrEmpty(service.Namespace) ? arg.OldValue as string : service.Namespace + '.' + arg.OldValue as string);
    KnownCodeTypes knownCodeTypes = KnownCodeTypes.FromStore(service.Store);
    CodeClass2 codeClass = knownCodeTypes.GetFullNamedType(oldFullName) as CodeClass2;
    CodeElement2 element = codeClass as CodeElement2;
    if (element != null)
    {
     element.RenameSymbol(arg.NewValue as string);
     knownCodeTypes.TakeIntoAccount(element as CodeType, true);
    }
   }
   else
    SynchronizeCodeWithModel(service);
  }



  internal static void Generate(TypeOfInterest type, CodeNamespace ns)
  {
   Service service = type as Service;
   CodeClass2 codeClass = IncrementalGenerator.EnsureClass(ns, type.Name) as CodeClass2;
   KnownCodeTypes.FromStore(type.Store).TakeIntoAccount(codeClass as CodeType, false);
   SynchronizeCodeWithModel(service);
  }

  private static void SynchronizeCodeWithModel(Service service)
  {
   KnownCodeTypes knownCodeTypes = KnownCodeTypes.FromStore(service.Store);
   if (knownCodeTypes == null)
    return;

   // Get the class
   CodeClass2 codeClass2 = knownCodeTypes.GetFullNamedType(service.FullName) as CodeClass2;
   if (codeClass2 != null)
   {
    // Class implements the interface
    foreach (Interface iface in service.ImplementedServiceContracts)
     IncrementalGenerator.EnsureClassImplementsInterface(codeClass2, iface.FullName);

    // Get the attribute (if necessary)
    CodeAttribute2 attribute = IncrementalGenerator.EnsureAttributeIff(codeClass2, "System.ServiceModel.ServiceBehaviorAttribute", true) as CodeAttribute2;

    // Ensure the arguments if necessary
    List<string> domainPropertiesToAttributeArgumentsMapping = new List<string>(new string[] 
                                                                {
                                                                  "AddressFilterMode",
                                                                  "AutomaticSessionShutdown",
                                                                  "ConcurrencyMode",
                                                                  "ConfigurationName",
                                                                  "IgnoreExtensionDataObject",
                                                                  "IncludeExceptionDetailInFaults",
                                                                  "InstanceContextMode",
                                                                  "MaxItemsInObjectGraph",
                                                                  "WSDLName->Name",
                                                                  "WSDLNamespace->Namespace",
                                                                  "ReleaseServiceInstanceOnTransactionComplete",
                                                                  "TransactionAutoCompleteOnSessionClose",
                                                                  "TransactionIsolationLevel",
                                                                  "TransactionTimeout",
                                                                  "UseSynchronizationContext",
                                                                  "ValidateMustUnderstand"
                                                                });
    IncrementalGenerator.EnsureAttributeArgumentsFromDomainProperties(service, attribute, domainPropertiesToAttributeArgumentsMapping);
   }
  }
 }
}
